home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / timed / measure.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-12-23  |  4.9 KB  |  186 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #ifndef lint
  14. static char sccsid[] = "@(#)measure.c    2.5 (Berkeley) 12/23/87";
  15. #endif /* not lint */
  16.  
  17. #include "globals.h"
  18. #include <protocols/timed.h>
  19. #include <netinet/in_systm.h>
  20. #include <netinet/ip.h>
  21. #include <netinet/ip_icmp.h>
  22.  
  23. #define BIASP         43199999
  24. #define BIASN        -43200000
  25. #define MODULO         86400000
  26. #define PROCESSING_TIME    5     /* ms. to reduce error in measurement */
  27.  
  28. #define PACKET_IN    1024
  29.  
  30. extern int id;
  31. int measure_delta;
  32. extern int sock_raw;
  33. static n_short seqno = 0;
  34.  
  35. /*
  36.  * Measures the differences between machines' clocks using
  37.  * ICMP timestamp messages.
  38.  */
  39.  
  40. measure(wait, addr)
  41. struct timeval *wait;
  42. struct sockaddr_in *addr;
  43. {
  44.     int length;
  45.     int status;
  46.     int msgcount, trials;
  47.     int cc, count;
  48.     fd_set ready;
  49.     long sendtime, recvtime, histime;
  50.     long min1, min2, diff;
  51.     register long delta1, delta2;
  52.     struct timeval tv1, tout;
  53.     u_char packet[PACKET_IN], opacket[64];
  54.     register struct icmp *icp = (struct icmp *) packet;
  55.     register struct icmp *oicp = (struct icmp *) opacket;
  56.     struct ip *ip = (struct ip *) packet;
  57.  
  58.     min1 = min2 = 0x7fffffff;
  59.     status = HOSTDOWN;
  60.     measure_delta = HOSTDOWN;
  61.  
  62. /* empties the icmp input queue */
  63.     FD_ZERO(&ready);
  64. empty:
  65.     tout.tv_sec = tout.tv_usec = 0;
  66.     FD_SET(sock_raw, &ready);
  67.     if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
  68.         length = sizeof(struct sockaddr_in);
  69.         cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, 
  70.             (struct sockaddr_in *)NULL, &length);
  71.         if (cc < 0)
  72.             return(-1);
  73.         goto empty;
  74.     }
  75.  
  76.     /*
  77.      * To measure the difference, select MSGS messages whose round-trip
  78.      * time is smaller than RANGE if ckrange is 1, otherwise simply
  79.      * select MSGS messages regardless of round-trip transmission time.
  80.      * Choose the smallest transmission time in each of the two directions.
  81.      * Use these two latter quantities to compute the delta between
  82.      * the two clocks.
  83.      */
  84.  
  85.     length = sizeof(struct sockaddr_in);
  86.     oicp->icmp_type = ICMP_TSTAMP;
  87.     oicp->icmp_code = 0;
  88.     oicp->icmp_cksum = 0;
  89.     oicp->icmp_id = id;
  90.     oicp->icmp_rtime = 0;
  91.     oicp->icmp_ttime = 0;
  92.     FD_ZERO(&ready);
  93.     msgcount = 0;
  94.     for (trials = 0; msgcount < MSGS && trials < TRIALS; ++trials) {
  95.         oicp->icmp_seq = ++seqno;
  96.         oicp->icmp_cksum = 0;
  97.  
  98.         tout.tv_sec = wait->tv_sec;
  99.         tout.tv_usec = wait->tv_usec;
  100.  
  101.             (void)gettimeofday (&tv1, (struct timezone *)0);
  102.         sendtime = oicp->icmp_otime = (tv1.tv_sec % (24*60*60)) * 1000 
  103.                             + tv1.tv_usec / 1000;
  104.         oicp->icmp_cksum = in_cksum((u_short *)oicp, sizeof(*oicp));
  105.     
  106.         count = sendto(sock_raw, (char *)opacket, sizeof(*oicp), 0, 
  107.                 addr, sizeof(struct sockaddr_in));
  108.         if (count < 0) {
  109.             status = UNREACHABLE;
  110.             return(-1);
  111.         }
  112.         for (;;) {
  113.             FD_SET(sock_raw, &ready);
  114.             if ((count = select(FD_SETSIZE, &ready, (fd_set *)0,
  115.                 (fd_set *)0, &tout)) <= 0)
  116.                 break;
  117.             cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, 
  118.                 (struct sockaddr_in *)NULL, &length);
  119.             (void)gettimeofday(&tv1, (struct timezone *)0);
  120.             if (cc < 0)
  121.                 return(-1);
  122.             icp = (struct icmp *)(packet + (ip->ip_hl << 2));
  123.             if((icp->icmp_type == ICMP_TSTAMPREPLY) &&
  124.                 icp->icmp_id == id && icp->icmp_seq == seqno)
  125.                 break;
  126.         }
  127.         if (count <= 0)
  128.             continue;        /* resend */
  129.         recvtime = (tv1.tv_sec % (24*60*60)) * 1000 +
  130.             tv1.tv_usec / 1000;
  131.         diff = recvtime - sendtime;
  132.         /*
  133.          * diff can be less than 0 aroud midnight
  134.          */
  135.         if (diff < 0)
  136.             continue;
  137.         msgcount++;
  138.         histime = ntohl((u_long)icp->icmp_rtime);
  139.         /*
  140.          * a hosts using a time format different from 
  141.          * ms. since midnight UT (as per RFC792) should
  142.          * set the high order bit of the 32-bit time
  143.          * value it transmits.
  144.          */
  145.         if ((histime & 0x80000000) != 0) {
  146.             status = NONSTDTIME;
  147.             break;
  148.         }
  149.         status = GOOD;
  150.         delta1 = histime - sendtime;
  151.         /*
  152.          * Handles wrap-around to avoid that around 
  153.          * midnight small time differences appear 
  154.          * enormous. However, the two machine's clocks
  155.          * must be within 12 hours from each other.
  156.          */
  157.         if (delta1 < BIASN)
  158.             delta1 += MODULO;
  159.         else if (delta1 > BIASP)
  160.             delta1 -= MODULO;
  161.         delta2 = recvtime - histime;
  162.         if (delta2 < BIASN)
  163.             delta2 += MODULO;
  164.         else if (delta2 > BIASP)
  165.             delta2 -= MODULO;
  166.         if (delta1 < min1)  
  167.             min1 = delta1;
  168.         if (delta2 < min2)
  169.             min2 = delta2;
  170.         if (diff < RANGE) {
  171.             min1 = delta1;
  172.             min2 = delta2;
  173.             break;
  174.         }
  175.     }
  176.  
  177.     /*
  178.      * If no answer is received for TRIALS consecutive times, 
  179.      * the machine is assumed to be down
  180.      */
  181.      if (status == GOOD) {
  182.         measure_delta = (min1 - min2)/2 + PROCESSING_TIME;
  183.     }
  184.     return(status);
  185. }
  186.